wayland: Avoid running stale cursor animation timeouts
authorCarlos Garnacho <carlosg@gnome.org>
Wed, 16 Sep 2015 10:21:36 +0000 (12:21 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Wed, 16 Sep 2015 17:19:49 +0000 (19:19 +0200)
gdk_wayland_device_update_window_cursor() is inconsistently returning
TRUE/FALSE, despite the timeout being always replaced for new cursor
frames. This could end up in these timeouts being "leaked" and running
as long as the window has an animated cursor.

Fix this by making it really sure we return G_SOURCE_REMOVE, although
now we keep track of animation delays, so the timeout will be reused
for constant time animations.

gdk/wayland/gdkdevice-wayland.c

index 792de22c37959f41ff236351af612389d3290065..92548858c1c6f60efdb490520c07d170c5af6adc 100644 (file)
@@ -94,6 +94,7 @@ struct _GdkWaylandDeviceData
   GdkCursor *grab_cursor;
   guint cursor_timeout_id;
   guint cursor_image_index;
+  guint cursor_image_delay;
 
   GdkDragContext *drop_context;
 
@@ -188,6 +189,7 @@ gdk_wayland_device_stop_window_cursor_animation (GdkWaylandDeviceData *wd)
       wd->cursor_timeout_id = 0;
     }
   wd->cursor_image_index = 0;
+  wd->cursor_image_delay = 0;
 }
 
 static gboolean
@@ -196,6 +198,7 @@ gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
   struct wl_buffer *buffer;
   int x, y, w, h, scale;
   guint next_image_index, next_image_delay;
+  gboolean retval = G_SOURCE_REMOVE;
 
   if (wd->grab_cursor)
     {
@@ -210,11 +213,11 @@ gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
   else
     {
       wd->cursor_timeout_id = 0;
-      return TRUE;
+      return retval;
     }
 
   if (!wd->wl_pointer)
-    return FALSE;
+    return retval;
 
   wl_pointer_set_cursor (wd->wl_pointer,
                          wd->enter_serial,
@@ -232,7 +235,7 @@ gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
     {
       /* We admit only static icons during drags so far */
       gdk_wayland_device_stop_window_cursor_animation (wd);
-      return TRUE;
+      return retval;
     }
 
   next_image_index =
@@ -242,21 +245,29 @@ gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
 
   if (next_image_index != wd->cursor_image_index)
     {
-      guint id;
+      if (next_image_delay != wd->cursor_image_delay)
+        {
+          guint id;
+
+          gdk_wayland_device_stop_window_cursor_animation (wd);
 
-      /* Queue timeout for next frame */
-      id = g_timeout_add (next_image_delay,
-                          (GSourceFunc)gdk_wayland_device_update_window_cursor,
-                          wd);
-      g_source_set_name_by_id (id, "[gtk+] gdk_wayland_device_update_window_cursor");
+          /* Queue timeout for next frame */
+          id = g_timeout_add (next_image_delay,
+                              (GSourceFunc)gdk_wayland_device_update_window_cursor,
+                              wd);
+          g_source_set_name_by_id (id, "[gtk+] gdk_wayland_device_update_window_cursor");
+          wd->cursor_timeout_id = id;
+        }
+      else
+        retval = G_SOURCE_CONTINUE;
 
-      wd->cursor_timeout_id = id;
       wd->cursor_image_index = next_image_index;
+      wd->cursor_image_delay = next_image_delay;
     }
   else
-    wd->cursor_timeout_id = 0;
+    gdk_wayland_device_stop_window_cursor_animation (wd);
 
-  return FALSE;
+  return retval;
 }
 
 static void